use std::{sync::Arc, collections::BTreeMap};
use parking_lot::RwLock;
use crate::data::log_record::LogRecodePos;
use crate::index::Indexer;

pub struct BTree {
    tree: Arc<RwLock<BTreeMap<Vec<u8>, LogRecodePos>>>,
}

impl BTree {
    pub fn new() -> Self {
        Self {
            tree: Arc::new(RwLock::new(BTreeMap::new())),
        }
    }
}


impl Indexer for BTree {
    fn put(&self, key: Vec<u8>, pos: LogRecodePos) -> bool {
        let mut wirte_guard = self.tree.write();
        match wirte_guard.insert(key, pos) {
            None => true,
            Some(_) => false,
        }
    }
    fn del(&self, key: Vec<u8>) -> bool {
        let option = self.tree.write().remove(&key);
        // match option {
        //     None => false,
        //     Some(_) => true,
        // }
        // 方法2
        // option.is_some()
        option.is_some()
    }

    fn get(&self, key: Vec<u8>) -> Option<LogRecodePos> {
        let read_guard = self.tree.read();
        match read_guard.get(&key).copied() {
            Some(pos) => Some(pos),
            None => None,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_btree_get_nonexistent() {
        let btree = BTree::new();
        let re = btree.get(vec![1, 2, 3]);
        assert_eq!(re, None);
    }

    #[test]
    fn test_btree_del_nonexistent() {
        let btree = BTree::new();
        let re = btree.del(vec![1, 2, 3]);
        assert_eq!(re, false);
    }

    #[test]
    fn test_btree_put_duplicate() {
        let btree = BTree::new();
        let first = btree.put(vec![1, 2, 3], LogRecodePos { file_id: 1, offset: 10 });
        let second = btree.put(vec![1, 2, 3], LogRecodePos { file_id: 2, offset: 20 });
        assert_eq!(first, true);
        assert_eq!(second, false);
    }

}